#include "../LogStream.h"
#include <limits>
using namespace yhaida;
//*****************************namespace Detail*****************************
/*
  十进制、十六进制转换并写入buff函数
*/
namespace yhaida
{
    namespace Detail
    {
        const char digits[] = "0123456789";
        static_assert(strlen(digits) == 10);

        const char digitsHex[] = "0123456789abcdef";
        static_assert(sizeof(digitsHex) == 17);
        //十进制

        template <typename T>
        size_t convert(char *buff, T value)
        {
            bool flag = value > 0 ? true : false;
            char *cur = buff;
            do
            {
                int temp = value % 10;
                value /= 10;
                *cur++ = digits[temp];
            } while (value != 0);
            if (!flag)
                *cur++ = '-';
            *cur = '\0';
            std::reverse(buff, cur);
            return cur - buff;
        }
        //十六进制
        size_t convertHex(char *buff, uintptr_t value)
        {
            char *cur = buff;

            do
            {
                int temp = value % 16;
                value /= 16;
                *cur++ = digits[temp];
            } while (value != 0);

            *cur = '\0';
            std::reverse(buff, cur);
            return cur - buff;
        }
    }
}

//*****************************namespace LogStream*****************************
void LogStream::staticCheck()
{
    //比较常用的使用是对于给定的基础类型用来判断在当前系统上的最大值、最小值。
    // std::numeric_limits<T>::digits10 ，返回目标类型在十进制下可以表示的最大位数，
    // :digits10是可以保留而不会丢失的小数位数。
    static_assert(kMaxNumericSize - 10 > std::numeric_limits<double>::digits10);
    static_assert(kMaxNumericSize - 10 > std::numeric_limits<long double>::digits10);
    static_assert(kMaxNumericSize - 10 > std::numeric_limits<long>::digits10);
    static_assert(kMaxNumericSize - 10 > std::numeric_limits<long long>::digits10);
}

template <typename T>
void LogStream::formatInt(T value)
{
    if (_buffer.intVail() >= kMaxNumericSize)
    {
        size_t length = yhaida::Detail::convert(_buffer.current(), value);
        _buffer.addLength(length);
    }
}

LogStream &LogStream::operator<<(bool flag)
{
    _buffer.push_data(flag ? "1" : "0", 0);
    return *this;
}
// short->2字节，int->4字节
LogStream &LogStream::operator<<(short value)
{
    *this << static_cast<int>(value);
    return *this;
}
LogStream &LogStream::operator<<(unsigned short value)
{
    *this << static_cast<unsigned int>(value);
    return *this;
}
LogStream &LogStream::operator<<(int value)
{
    formatInt(value);
    return *this;
}
LogStream &LogStream::operator<<(unsigned int value)
{
    formatInt(value);
    return *this;
}
LogStream &LogStream::operator<<(long value)
{
    formatInt(value);
    return *this;
}
LogStream &LogStream::operator<<(unsigned long value)
{
    formatInt(value);
    return *this;
}
LogStream &LogStream::operator<<(long long value)
{
    formatInt(value);
    return *this;
}
LogStream &LogStream::operator<<(unsigned long long value)
{
    formatInt(value);
    return *this;
}
LogStream &LogStream::operator<<(const char *value)
{
    //去掉'\0'
    _buffer.push_data(value, strlen(value));
    return *this;
}
LogStream &LogStream::operator<<(char value)
{
    _buffer.push_data(&value, 1);
    return *this;
}
// float->4字节，double->8字节
LogStream &LogStream::operator<<(float value)
{
    *this << static_cast<double>(value);
    return *this;
}
LogStream &LogStream::operator<<(double value)
{
    if (_buffer.intVail() >= kMaxNumericSize)
    {
        size_t length = yhaida::Detail::convertHex(_buffer.current(), value);
        _buffer.addLength(length);
    }
    return *this;
}
LogStream &LogStream::operator<<(const std::string &value)
{
    _buffer.push_data(value.c_str(), value.size());
    return *this;
}
LogStream &LogStream::operator<<(const void *p)
{
    uintptr_t value = reinterpret_cast<uintptr_t>(p);
    if (_buffer.intVail() >= kMaxNumericSize)
    {
        char *tempBuf = _buffer.current();
        *tempBuf++ = '0';
        *tempBuf++ = 'x';
        size_t length = yhaida::Detail::convertHex(tempBuf, value);
        _buffer.addLength(length);
    }
    return *this;
}

LogStream &LogStream::operator<<(const Detail::T &value)
{
    _buffer.push_data(value._str, value._length);
    return *this;
}

//显示模板特例化
template Fmt::Fmt(const char *fmt, char);
template Fmt::Fmt(const char *fmt, short);
template Fmt::Fmt(const char *fmt, unsigned short);
template Fmt::Fmt(const char *fmt, int);
template Fmt::Fmt(const char *fmt, unsigned int);
template Fmt::Fmt(const char *fmt, long);
template Fmt::Fmt(const char *fmt, unsigned long);
template Fmt::Fmt(const char *fmt, long long);
template Fmt::Fmt(const char *fmt, unsigned long long);
template Fmt::Fmt(const char *fmt, float);
template Fmt::Fmt(const char *fmt, double);
